package com.cong.modules.sys.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.cong.common.constant.CoreConst;
import com.cong.common.util.AuthorizationUtils;
import com.cong.common.util.PageUtil;
import com.cong.common.util.StringUtils;
import com.cong.common.util.UUIDUtil;
import com.cong.common.util.text.Convert;
import com.cong.common.vo.AjaxResultVo;
import com.cong.modules.base.BaseController;
import com.cong.modules.sys.model.SysMenu;
import com.cong.modules.sys.model.SysRole;
import com.cong.modules.sys.model.SysUser;
import com.cong.modules.sys.service.MenuService;
import com.cong.modules.sys.service.RoleService;
import com.cong.modules.sys.service.UserService;
import com.cong.modules.sys.vo.MenuTreeListVo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/role")
public class RoleController extends BaseController {

    @Resource
    private RoleService roleService;

    @Resource
    private MenuService menuService;

    @Resource
    private UserService userService;

    /**
     * 权限管理--角色管理
     */
    @GetMapping("/toRolePage")
    public String roleList() {
        return "role/list";
    }

    /**
     * 角色列表数据
     *
     * @param role 角色实体
     * @param limit 查询限制条数
     * @param offset 查询起点
     * @return 返回角色列表数据
     */
    @RequiresPermissions("role:list")
    @PostMapping("/list")
    @ResponseBody
    public AjaxResultVo pageRoles(SysRole role, Integer limit, Integer offset) {
        try {
            PageHelper.startPage(PageUtil.getPageNo(limit, offset), limit);
            List<SysRole> roleList = roleService.listRoles(role);
            PageInfo<SysRole> pageResult = new PageInfo<>(roleList);
            AjaxResultVo resultVo = AjaxResultVo.success();
            resultVo.put("rows", pageResult.getList());
            resultVo.put("total", pageResult.getTotal());
            return resultVo;
        } catch (Exception e) {
            logger.error(String.format("角色列表查询异常 RoleController.pageRoles%s", e));
            return AjaxResultVo.error("查询失败");
        }
    }

    /**
     * 跳转新增角色
     */
    @RequiresPermissions("role:add")
    @GetMapping("/add")
    public String add() {
        return "role/add";
    }

    /**
     * 添加角色
     *
     * @param role 角色数据
     * @return 返回角色添加结果
     */
    @RequiresPermissions("role:add")
    @PostMapping("/doAdd")
    @ResponseBody
    public AjaxResultVo addRole(SysRole role) {
        try {
            Date nowDate = new Date();
            role.setRoleId(Long.valueOf(UUIDUtil.getUniqueIdByUUId()));
            role.setCreateTime(nowDate);
            role.setUpdateTime(nowDate);
            if (roleService.save(role)) {
                return AjaxResultVo.success("添加角色成功");
            } else {
                return AjaxResultVo.error("添加角色失败");
            }
        } catch (Exception e) {
            logger.error(String.format("角色添加异常 RoleController.addRole%s", e));
            return AjaxResultVo.error("添加角色失败");
        }
    }

    /**
     * 编辑角色详情
     *
     * @param model 页面跳转实体
     * @param roleId 角色ID
     * @return 返回角色详情页面
     */
    @RequiresPermissions("role:edit")
    @GetMapping("/edit")
    public String detail(Model model, String roleId) {
        SysRole role = roleService.getSysRoleById(Long.valueOf(roleId));
        model.addAttribute("role", role);
        return "role/detail";
    }

    /**
     * 编辑角色
     *
     * @param role 角色ID
     * @return 返回角色编辑结果
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResultVo editRole(SysRole role) {
        try {
            role.setUpdateTime(new Date());
            if (roleService.updateById(role)) {
                return AjaxResultVo.success("编辑角色成功");
            } else {
                return AjaxResultVo.error("编辑角色失败");
            }
        } catch (Exception e) {
            logger.error(String.format("角色编辑异常 RoleController.editRole%s", e));
            return AjaxResultVo.error("编辑角色失败");
        }
    }

    /**
     * 删除角色
     *
     * @param roleId 角色ID
     * @return 返回角色删除结果
     */
    @RequiresPermissions("role:delete")
    @PostMapping("/delete")
    @ResponseBody
    public AjaxResultVo deleteRole(String roleId) {
        try {
            if (StringUtils.isEmpty(roleId)) {
                return AjaxResultVo.error("删除失败,未选择删除选项");
            }
            Long[] roleIds = {Long.valueOf(roleId)};
            if (roleService.listAllUsersByRoleIds(roleIds).size() > 0) {
                return AjaxResultVo.error("删除失败,该角色下存在用户");
            }
            List<Long> roleIdsList = Arrays.asList(roleIds);
            if (roleService.removeByIds(roleIdsList)) {
                // 删除角色菜单关系
                if (roleService.batchRemoveRoleAndMenu(roleIdsList)) {
                    return AjaxResultVo.success("删除角色成功");
                } else {
                    return AjaxResultVo.error("删除角色失败");
                }
            } else {
                return AjaxResultVo.error("删除角色失败");
            }
        } catch (Exception e) {
            logger.error(String.format("角色删除异常 RoleController.deleteRole%s", e));
            return AjaxResultVo.error("删除角色失败");
        }
    }

    /**
     * 批量删除角色
     *
     * @param roleIdStr 角色ID字符串
     * @return 返回角色批量删除结果
     */
    @RequiresPermissions("role:delete")
    @PostMapping("/batch/delete")
    @ResponseBody
    public AjaxResultVo batchDeleteRole(String roleIdStr) {
        try {
            Long[] roleIdsArray = Convert.toLongArray(",", roleIdStr);
            if (StringUtils.isEmpty(roleIdsArray)) {
                return AjaxResultVo.error("删除失败,未选择删除选项");
            }
            if (roleService.listAllUsersByRoleIds(roleIdsArray).size() > 0) {
                return AjaxResultVo.error("删除失败,选择的角色下存在用户");
            }
            List<Long> roleIdsList = Arrays.asList(roleIdsArray);
            if (roleService.removeByIds(roleIdsList)) {
                // 删除角色菜单关系
                if (roleService.batchRemoveRoleAndMenu(roleIdsList)) {
                    return AjaxResultVo.success("删除角色成功");
                } else {
                    return AjaxResultVo.error("删除角色失败");
                }
            } else {
                return AjaxResultVo.error("删除角色失败");
            }
        } catch (Exception e) {
            logger.error(String.format("批量删除角色异常 RoleController.batchDeleteRole%s", e));
            return AjaxResultVo.error("删除角色失败");
        }
    }

    /**
     * 分配权限详情
     *
     * @param model 页面跳转实体
     * @param roleId 角色ID
     * @return 分配权限详情
     */
    @RequiresPermissions("role:edit")
    @GetMapping("/assignMenus")
    public String assignMenus(Model model, String roleId) {
        model.addAttribute("roleId", roleId);
        return "role/assignmenus";
    }

    /**
     * 分配权限列表查询
     *
     * @param roleId 角色ID
     * @return 返回分配权限列表数据
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/assign/menu/list")
    @ResponseBody
    public List<MenuTreeListVo> assignRole(String roleId) {
        List<MenuTreeListVo> listVos = new ArrayList<>();
        List<SysMenu> allMenus = menuService.listAllPermsByStatus(CoreConst.STATUS_VALID);
        List<SysMenu> hasMenus = roleService.listMenusByRoleId(Long.valueOf(roleId));
        for (SysMenu menu : allMenus) {
            MenuTreeListVo vo = new MenuTreeListVo();
            vo.setMenuId(menu.getMenuId());
            vo.setName(menu.getName());
            vo.setParentId(menu.getParentId());
            for (SysMenu hasMenu : hasMenus) {
                // 有权限则选中
                if (hasMenu.getMenuId().equals(menu.getMenuId())) {
                    vo.setChecked(true);
                    break;
                }
            }
            listVos.add(vo);
        }
        return listVos;
    }

    /**
     * 分配权限
     *
     * @param roleId 角色ID
     * @param menuIdStr 菜单ID字符串
     * @return 返回分配权限结果
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/assign/menu")
    @ResponseBody
    public AjaxResultVo assignRole(String roleId, String menuIdStr) {
        try {
            List<Long> menuIdsList = new ArrayList<>();
            if (StringUtils.isNotBlank(menuIdStr)) {
                Long[] menuIdArray = Convert.toLongArray(",", menuIdStr);
                menuIdsList = Arrays.asList(menuIdArray);
            }
            AjaxResultVo resultVo = roleService.addAssignMenu(Long.valueOf(roleId), menuIdsList);
            AuthorizationUtils.clearAllCachedAuthorizationInfo();
            return resultVo;
        } catch (Exception e) {
            logger.error(String.format("分配权限异常 RoleController.assignRole%s", e));
            return AjaxResultVo.error("分配权限失败");
        }
    }

    /**
     * 分配角色详情
     *
     * @param model 页面跳转实体
     * @param roleId 角色ID
     * @return 返回分配角色详情
     */
    @RequiresPermissions("role:edit")
    @GetMapping("/assignUsers")
    public String assignUsers(Model model, String roleId) {
        model.addAttribute("roleId", roleId);
        return "role/assignusers";
    }

    /**
     * 分配角色列表查询
     *
     * @param roleId 角色ID
     * @return 返回分配角色列表数据
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/assign/user/list")
    @ResponseBody
    public AjaxResultVo assignUserList(String roleId) {
        try {
            List<SysUser> userList = userService.listUsers(new SysUser());
            Set<Long> hasUsers = roleService.listUserIdsByRoleId(Long.valueOf(roleId));
            AjaxResultVo resultVo = AjaxResultVo.success();
            resultVo.put("rows", userList);
            resultVo.put("hasUsers", hasUsers);
            return resultVo;
        } catch (Exception e) {
            logger.error(String.format("分配角色列表查询异常 RoleController.assignUserList%s", e));
            return AjaxResultVo.error("查询失败");
        }
    }

    /**
     * 取消角色分配
     *
     * @param roleId 角色ID
     * @param userId 用户ID
     * @return 返回取消角色分配
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/cancelAssign")
    @ResponseBody
    public AjaxResultVo cancelAssign(String roleId, String userId) {
        try {
            return roleService.cancelAssign(Long.valueOf(roleId), Long.valueOf(userId));
        } catch (Exception e) {
            logger.error(String.format("取消角色分配异常 RoleController.cancelAssign%s", e));
            return AjaxResultVo.error("取消角色分配失败");
        }
    }

    /**
     * 分配用户
     *
     * @param roleId 角色ID
     * @param userId 用户ID
     * @return 返回分配用户结果
     */
    @RequiresPermissions("role:edit")
    @PostMapping("/assignUser")
    @ResponseBody
    public AjaxResultVo assignUser(String roleId, String userId) {
        try {
            return roleService.assignUser(Long.valueOf(roleId), Long.valueOf(userId));
        } catch (Exception e) {
            logger.error(String.format("分配用户异常 RoleController.assignUser%s", e));
            return AjaxResultVo.error("分配用户失败");
        }
    }

}
